package abel.wlmr.model.type;

import abel.util.HexString;
import abel.wlmr.model.WlmrBaseUnit;
import abel.wlmr.model.WlmrException;
import io.netty.buffer.ByteBuf;

public class ErcBaseBody extends WlmrBaseUnit {

    protected static final int MIN_LENGTH = 1 + 1;

    protected short erc;

    protected short le;

    private HexString rest;

    /**
     * 
     */
    public ErcBaseBody(short erc, short le) {
        this((short) -1, erc, le);
    }

    /**
     * @param erc
     */
    public ErcBaseBody(short guessedLen, short erc, short le) {
        super(guessedLen);
        this.erc = erc;
        this.le = le;
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.AppUnitBody#appendBuf(io.netty.buffer.ByteBuf)
     */
    @Override
    public ByteBuf appendBuf(ByteBuf buf) {
        if (rest == null || rest.length() != le) {
            throw new IllegalArgumentException("not enough bytes in erc body");
        }
        if (erc < 0 || le < 0) {
            throw new IllegalArgumentException("erc & le should be set before appending.");
        }

        buf.writeByte(erc);
        buf.writeByte(le);
        buf.writeBytes(rest.getBs());

        return buf;
    }

    /* (non-Javadoc)
     * @see abel.wlmr.model.AppUnitBody#parseBuf(io.netty.buffer.ByteBuf)
     */
    @Override
    public int parseBuf(ByteBuf buf) throws WlmrException {
        if (buf.readableBytes() < MIN_LENGTH) {
            return -1;
        }

        ByteBuf dup = buf.duplicate();

        erc = (short) (dup.readByte() & 0xFF);
        le = (short) (dup.readByte() & 0xFF);

        if (le > buf.readableBytes()) {
            return -1;
        }

        buf.skipBytes(MIN_LENGTH);
        rest = new HexString(buf, le);

        return MIN_LENGTH + le;
    }

    @Override
    public int getMinLength() {
        return MIN_LENGTH;
    }

    @Override
    public short getFinalLen() {
        if (finalLen < 0) {
            finalLen = (short) (MIN_LENGTH + le);
        }
        return finalLen;
    }

    /**
     * @return the erc
     */
    public short getErc() {
        return erc;
    }

    /**
     * @return the le
     */
    public short getLe() {
        return le;
    }

}
